/*-------------------
 *
 * op_list.h
 *   interface for openPlant ODBC generic linked list package
 * 
 * This package implements singly-linked homogeneous linst.
 * It is important to have constant-time length, append, and prepend
 * operations. To achieve this, we deal with two distinct data
 * structures:
 *
 * 1. A set of "list cells": each cell contains a data field and
 *    a link to the next cell in the list or NULL.
 * 2. A single structure containing metadata about the list: the
 *    type of the list, pointers to the head and tail cells, and
 *    the length of the list.
 *
 * We support three types of lists:
 *
 * T_List: lists of pointers
 *         (in practice usually pointers to Nodes, but not always;
 *         declared as "void *" to minimize casting annoyances)
 *	   T_IntList: lists of integers
 *	   T_OidList: lists of Oids
 *
 * (At the moment, ints and Oids are the same size, but they may not
 * always be so; try to be careful to maintain the distinction.)
 */
#ifndef OP_LIST_H
#define OP_LIST_H

#include "nodes/nodes.h"

typedef struct ListCell ListCell;

/* _line_045 */
typedef struct List
{
  NodeTag type;  /* T_List, T_IntList, or T_OidList */
  int length;
  ListCell *head;
  ListCell*tail;
} List;

/* _line_053 */
struct ListCell
{
  union
  {
    void *ptr_value;
    int int_value;
    unsigned int oid_value;
  }data;
  ListCell   *next;
};

/*
 * The *only* valid representation of an empty list is NIL; in other
 * words, a non-NIL list is guaranteed to have length >= 1 and
 * head/tail != NULL
 */
 /* _line_069 */
#define NIL ((List *) NULL)

/* _line_098 */
extern ListCell *list_head(List *l);
extern ListCell *list_tail(List *l);
extern int list_length(List *l);

/*
 * NB: There is an unfortunate legacy from a previous incarnation of
 * the List API: the macro lfirst() was used to mean "the data in this
 * cons cell". To avoid changing every usage of lfirst(), that meaning
 * has been kept. As a result, lfirst() takes a ListCell and returns
 * the data it contains; to get the data in the first cell of a
 * List, use linitial(). Worse, lsecond() is more closely related to
 * linitial() than lfirst(): given a List, lsecond() returns the data
 * in the second cons cell.
 */
/* _line_115 */
#define lnext(lc) ((lc)->next)
#define lfirst(lc) ((lc)->data.ptr_value)

/* convenience macro for building fixed-length lists */
#define list_make1(x1) lcons(x1, NIL);

/*
 * foreach -
 *	  a convenience macro which loops through the list
 */
#define foreach(cell, l)	\
	for ((cell) = list_head(l); (cell) != NULL; (cell) = lnext(cell))

/* _line_185 */
extern List *lappend(List *list, void *datum);
/* _line_193 */
extern List *lcons(void *datum, List *list);
/* _line_197 */
extern List *list_concat(List *list1, List *list2);


#endif  /* OP_LIST_H */
